#include "kernel.h"
#include  "global.h"
#include <stdio.h>
#include <unistd.h>

RTX:: RTX(){
	for( int i = 0; i < Num_Proc; i++ )
        {PCB_list[i] = NULL;}
        cur_proc=NULL;
        system_time=0;
        free_env_Q=NULL;
	//not for partial	ready_queue; //with 4 priority queues
	//not for partial	blocked_queue; //with 2 priority queues
	//send_trace_buffer[TraceBufferSize];
	//receive_trace_buffer[TraceBufferSize];
}

void RTX:: initialization(initTable init_table[]){
 for(int i=0;i<Num_Proc;i++){
        
                    //put the values in init_table into according fields in PCBs
                    PCB_list[i]=new PCB;
                    PCB_list[i]->next=NULL;
                    PCB_list[i]->msgQ=new MsgEnvQ();
                    PCB_list[i]->pid=init_table[i].pid;
                    PCB_list[i]->priority=init_table[i].priority;
                    PCB_list[i]->status=init_table[i].status;
                    //	PCB_list[i]->stack=new int *  //not needed for partial
                    //	[init_table[i].stack_size],init_table[i].stack_size;  // not in partial
                    PCB_list[i]->address=init_table[i].start_address;
                    
         }
          //init_MsgEn
        free_env_Q = new MsgEnvQ(Num_MsgEnv);
        //setjmp, longjmp to start porcesses here
        //not for partial

 	 //current_process = procP PCB
 	 cur_proc=PCB_list[ProcessP];
 	 //current_process->status = NEVER_BLK_PROC
 	// PCB_list[ProcessP]->status=NEVER_BLK_PROC;

}		 

PCB * RTX:: search_PCB(int target_pid){
    PCB * temp_PCB;
    int i=0;
    printf("\n the PCB we want to find is %i\n",target_pid);
    while(i<Num_Proc){
        temp_PCB=PCB_list[i];
        if (temp_PCB->pid==target_pid)
        {
           printf("\n the search PCB got the PCB %i\n",temp_PCB->pid);
           return temp_PCB;                            
        }
        else
        {i++;printf("\n the search PCB go to the next PCB \n");}
    }
    printf("\n the search PCB DID NOT got the PCB \n");
    return NULL;
}			 
/*
void RTX::addTrace(MsgEnv*){
	  return;
}				 

void RTX::process_switch(){
	  
	  PCB *next_proc;
	  next_proc=ready_queue.dequeue();//make local next
	  process pointer pointing to the highest priority process on
	  ready Q;
	  next_proc->status=executing;
	  context_switch(next_proc);
	  return;
}

void RTX::context_switch(PCB * next){
	  if (setjmp(cur_porc->procContext)==0){
	  	  longjmp(next_proc->procContext, 1);
	  	  cur_proc=next_proc;//cur_process is point the new
	  	  process now
	  }
	  return;
}	
	 
void RTX::rpq_enqueue(PCB* newPcb){
	  //ready_queue.enqueue();	  
	  return -1;
}		 
PCB* RTX::rpq_dequeue(){
	  //return the PCB with the highest priority
	  //ready_queue.dequeue();
	  return -1;
}		 
				 
*/


//the primitives!!	
int RTX::send_message(int dest_pid, MsgEnv *msg_envelope )
{//made some changes here, we only need one argument for this function since the envelope passed into the send message function will contain the target pid.
 //We need a way to get the PCB pointer from the pid. It should be easy because we know which process the message is going to be sent to
      PCB *dest_PCB;
      
      msg_envelope->target_pid = dest_pid;
      printf("\n the dest process for send is %i \n",dest_pid);
      dest_PCB=search_PCB(dest_pid);//dest_PCB is a pointer to the destination process
      printf("\n search pcb complted\n");
      printf("\n pid of the dest process is %i \n",dest_PCB->pid);
      dest_PCB->msgQ->enqueue(msg_envelope);//put msg onto msg Q of dest_PCB
      
      printf("\n msg inqueued\n");
 	//if (dest_process_id.status == 3)//however, if destination process status=blocked on receive
 	//{
    //            dest_PCB.status=2//set status to ready
 	// 	rpq.enqueue (Msg_Env, dest_PCB);
    //           addTrace(Msg_Env);
    //    }
//printf("\nmsg received!\n");
return 1;
}


MsgEnv * RTX:: receive_message( )
{
 	//MsgEnv *msg_env;
 	MsgEnv *temp;
 	//printf("the size fo the msgQ on Process P is %s\n",PCB_list[ProcessP]->msgQ->getsize());
        while (cur_proc->msgQ->getsize()==0 ) {//if no msg to receive or status = 5(NO BLOCK RECEIVE)
                //printf("msgQ on Process is empty\n");
                return NULL;
        //addtrace(MsgEnv*);//not in partial
        }
        
        temp=cur_proc->msgQ->dequeue(); 
        printf("dequeue in recieve success\n");
        return temp;
}

int RTX:: send_console_chars(MsgEnv * message_envelope ){
//Used to display text on CRT

//Send MsgEnv pointer and process ID to CRT Iprocess
message_envelope->sender_pid=cur_proc->pid;
message_envelope->target_pid=1;//CRT==1
message_envelope->type=4;//request_output

send_message(message_envelope->sender_pid,message_envelope);

//Force CRT i_proc to run once
//CRT_iproc();

}

int RTX:: get_console_chars(MsgEnv * message_envelope ){
//Used to recieve input from user/KB
if(message_envelope==NULL)
{return -1;}
message_envelope->sender_pid=cur_proc->pid;
message_envelope->target_pid=0; //KB Iproc
message_envelope->type=request_input;//request_input
//kbd_handler(SIGUSR1);
printf("\n msg chars got\n");
return 0;
//force Run KB i_process once
//KB_iproc(cur_proc->pid);

}

